package icu.groot.alan.hotel.util;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Supplier;
import java.util.regex.Pattern;

public class GrootApi {
    public static void main(String[] args) {
        // 测试 正则匹配号码
        boolean b = Check.checkPhone("13438633781");
        System.out.println(b);
        // 测试jwt
//        String token = Jwt.create("1001");
//        System.out.println(token);

//        LinkedList<String> validate = Jwt.validate("GROOT@eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxMDAxIiwiZXhwIjoxNjc3MTI1NzI0fQ.IyoSEB9OfG48zM160feKUyMGtWKN3uEL9ywF_WMlkU23e1e-sXtwPURPzibHA4YNNZNTIR-uK5TSQRO7dgZx1Q");
//        System.out.println(validate.get(0));
//        System.out.println(validate.get(1));
    }

    /**
     * 正则校验类
     */
    public static class Check{
        /**
         * 大陆手机号码11位数，匹配格式：前三位固定格式+后8位任意数
         */
        public static boolean checkPhone(String phone) {
            try {
                return Pattern
                        .compile(
                                "^((13[0-9])|(14[05679])|(15([0-3,5-9]))|(16[2567])|(17[01235678])|(18[0-9]|19[135689]))\\d{8}$"
                        )
                        .matcher(phone)
                        .matches();
            }catch (Exception e){
                return false;
            }
        }
    }

    /**
     * Jwt类
     */
    public static class Jwt{

        /**
         * 定义token返回头部:存储信息
         */
        public final static String HEADER = "login-token";
        public final static String HEADER_ADMIN = "admin-token";

        /**
         * 签发者
         */
        public final static String ISSUER = "GROOT";

        /**
         * token前缀
         */
        private final static String TOKEN_PRE_FIX = "GROOT@";

        /**
         * 签名密钥
         */
        private final static String SECRET = "Alan-4021@groot.icu";

        /**
         * 有效期/分钟*60*1000
         */
        private static final long EXPIRE_TIME = 2 * 60 * 1000;

        /**
         * 存进客户端的token的key名
         */
        public static final String IDENTITY = "IDENTITY";

        /**
         * 创建TOKEN
         */
        public static String create(String sub){
            return TOKEN_PRE_FIX + JWT.create()
                    .withSubject(sub)
                    .withIssuer(ISSUER)
                    .withIssuedAt(new Date())
                    .withExpiresAt(new Date(System.currentTimeMillis() + EXPIRE_TIME))
                    .sign(Algorithm.HMAC512(SECRET));
        }

        /**
         * 验证token
         */
        public synchronized static LinkedList<String> validate(String token){
            try {
                DecodedJWT verify = JWT.require(Algorithm.HMAC512(SECRET))
                        .build()
                        .verify(token.replace(TOKEN_PRE_FIX, ""));
                // 更新token
                String updateToken = update(verify);
                LinkedList<String> info = new LinkedList<>();
                info.add(updateToken == null ? token : updateToken);
                info.add(verify.getSubject());
                return info;
            } catch (TokenExpiredException e){
                e.printStackTrace();
                throw new RuntimeException("token过期");
            } catch (Exception e){
                e.printStackTrace();
                throw new RuntimeException("token异常");
            }
        }

        /**
         * 检查token是否需要更新
         */
        private static String update(DecodedJWT jwt){
            return (jwt.getExpiresAt().getTime()-System.currentTimeMillis()) < (EXPIRE_TIME >> 1) ? create(jwt.getSubject()) : null;
        }
    }

    /**
     * BeanUtils扩展类：可复制列表
     */
    public static class BeanCopy extends BeanUtils {

        public static <S, T> T convertTo(S source, Supplier<T> targetSupplier) {
            return convertTo(source, targetSupplier, null);
        }

        /**
         * 转换对象
         *
         * @param source         源对象
         * @param targetSupplier 目标对象供应方
         * @param callBack       回调方法
         * @param <S>            源对象类型
         * @param <T>            目标对象类型
         * @return 目标对象
         */
        public static <S, T> T convertTo(S source, Supplier<T> targetSupplier, icu.groot.alan.hotel.util.spring.BeanCopy.ConvertCallBack<S, T> callBack) {
            if (null == source || null == targetSupplier) {
                return null;
            }

            T target = targetSupplier.get();
            copyProperties(source, target);
            if (callBack != null) {
                callBack.callBack(source, target);
            }
            return target;
        }

        public static <S, T> List<T> convertListTo(List<S> sources, Supplier<T> targetSupplier) {
            return convertListTo(sources, targetSupplier, null);
        }

        /**
         * 转换对象
         *
         * @param sources        源对象list
         * @param targetSupplier 目标对象供应方
         * @param callBack       回调方法
         * @param <S>            源对象类型
         * @param <T>            目标对象类型
         * @return 目标对象list
         */
        public static <S, T> List<T> convertListTo(List<S> sources, Supplier<T> targetSupplier, icu.groot.alan.hotel.util.spring.BeanCopy.ConvertCallBack<S, T> callBack) {
            if (null == sources || null == targetSupplier) {
                return null;
            }

            List<T> list = new ArrayList<>(sources.size());
            for (S source : sources) {
                T target = targetSupplier.get();
                copyProperties(source, target);
                if (callBack != null) {
                    callBack.callBack(source, target);
                }
                list.add(target);
            }
            return list;
        }

        /**
         * 回调接口
         *
         * @param <S> 源对象类型
         * @param <T> 目标对象类型
         */
        @FunctionalInterface
        public interface ConvertCallBack<S, T> {
            void callBack(S t, T s);
        }
    }

    /**
     * 枚举工具类
     */
    public static class EnumUtil {}

    public static class DateFormat {
        /**
         *
         */
//        public static
    }

}
